package com.seed.bpmn.provider.camunda.common.cmd;

import com.seed.bpmn.engine.common.constants.BpmnConstants;
import com.seed.bpmn.engine.dto.ScheduleDTO;
import com.seed.bpmn.provider.camunda.common.util.DTOUtil;
import org.camunda.bpm.engine.impl.context.Context;
import org.camunda.bpm.engine.impl.interceptor.Command;
import org.camunda.bpm.engine.impl.interceptor.CommandContext;
import org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity;
import org.camunda.bpm.engine.impl.persistence.entity.TaskEntity;
import org.camunda.bpm.engine.impl.pvm.process.ActivityImpl;
import org.camunda.bpm.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperation;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 流程调度Command
 */
public class ScheduleCmd implements Command<ScheduleDTO> {

    /** 目标流程定义环节ID */
    private String activityId;

    /** 流程实例ID */
    private String processInstanceId;

    /** 跳转原因 */
    private String reason;

    /** 变量参数 候选人，候选组 */
    private Map<String, Object> variables;

    public ScheduleCmd(String processInstanceId, String activityId, Map<String, Object> variables) {
        this(processInstanceId, activityId, variables, "schedule");
    }

    public ScheduleCmd(String processInstanceId, String activityId, Map<String, Object> variables, String reason) {
        this.activityId = activityId;
        this.processInstanceId = processInstanceId;
        this.variables = variables;
        this.reason = reason;
    }

    @Override
    public ScheduleDTO execute(CommandContext commandContext) {
        ScheduleDTO s = new ScheduleDTO();
        try {
            ExecutionEntity executionEntity = commandContext.getExecutionManager().findExecutionById(processInstanceId);

            ProcessDefinitionImpl processDefinition = executionEntity.getProcessDefinition();
            ActivityImpl activity = processDefinition.findActivity(activityId);

            String type = (String)activity.getProperty(BpmnConstants.ATTRIBUTE_TYPE);
            boolean multiInstance = activity.isMultiInstance();

            //删除执行实例
            List<ExecutionEntity> executions = commandContext.getExecutionManager().findExecutionsByProcessInstanceId(processInstanceId);
            for(ExecutionEntity e : executions) {
                if(!e.getId().equals(processInstanceId)){
                    e.remove();
                }
            }

            //删除待办任务
            Iterator<TaskEntity> tasks = Context.getCommandContext().getTaskManager().findTasksByProcessInstanceId(processInstanceId).iterator();
            while (tasks.hasNext()){
                TaskEntity task = tasks.next();

                //添加调度中完成的老待办任务到调度对象中
                s.getCompleteTasks().add(DTOUtil.getTaskDTO(task));

                task.fireEvent("complete");
                Context.getCommandContext().getTaskManager().deleteTask(task,"scheduleCompleted",false,true);
            }

            //目标节点为多实例节点
            if(BpmnConstants.ELEMENT_SUBPROCESS.equals(type) || multiInstance){
                activity = (ActivityImpl)activity.getFlowScope();
            }

            executionEntity.setVariables(this.variables);
            executionEntity.setActivity(activity);
            executionEntity.setActivityInstanceId((String)null);
            executionEntity.performOperation(PvmAtomicOperation.ACTIVITY_START_CREATE_SCOPE);

            s.setMessage("调度成功！");
            s.setSuccess(true);
        }catch (Exception e){
            s.setMessage("调度失败！"+e.getMessage());
            s.setSuccess(true);
        }
        return s;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }
}
